# coding=utf-8
import os
import time
import threading
import gpu_port_ip_map as Port_ip_map

GPU_PER_SERVER = 8
GPU_NUM = 64
LEAF_NUM = 2
SPINE_NUM = 1
TASK_THREADING_MAP = {}
CURRENT_COMMAND_ID = 441
GPU_OCCUPIED_SET = set()
GLOBAL_GPU_LIST = [ 
24,25,26,27,28,29,30,31,
32,33,34,35,36,37,38,39,
48,49,50,51,52,53,54,55,
40,41,42,43,44,45,46,47,
16,17,18,19,20,21,22,23,
0,1,2,3,4,5,6,7,
8,9,10,11,12,13,14,15
]

SERVER_IP_LIST = [ 
"10.174.216.254",
"10.174.216.255",
"10.174.217.5",
"10.174.217.0",
"10.174.217.1",
"10.174.217.3",
"10.174.217.2",
"10.174.217.4",
]
  
    

def scheduler_interface(taskid, task_GPUS_num, sim_time):
    success = True
    success, gpu_index, job_gpu_leaf_port_map, job_gpu_spine_port_map= scheduler.schedule(task_GPUS_num, taskid, sim_time)
    if success:
        print(gpu_index)
        return success, gpu_index, job_gpu_leaf_port_map, job_gpu_spine_port_map
    else:
        return success, None, None, None

def get_acl_para(flow_port_list):
    start_gpu = flow_port_list[0]
    leaf_outport = flow_port_list[1] - GPU_NUM
    spine_inport = flow_port_list[2] - 2*GPU_NUM
    spine_outport = flow_port_list[3] - 2*GPU_NUM
    leaf_inport = flow_port_list[4] - GPU_NUM
    dis_gpu = flow_port_list[5]
    global CURRENT_COMMAND_ID
    comm_para_list_for_this_task = []
    if start_gpu>=int(GPU_NUM/2):
        # 1 正方向leaf源路由
        # global CURRENT_COMMAND_ID
        comm_para_list_for_this_task.append(("H", Port_ip_map.find_gpu_ip(start_gpu), Port_ip_map.find_spine_ip(int(leaf_outport)), Port_ip_map.find_hw_leaf_port(start_gpu%32), CURRENT_COMMAND_ID))
        CURRENT_COMMAND_ID += 1
    else:
        # global CURRENT_COMMAND_ID
        start_vlan_id = Port_ip_map.rg_vlan_list[int(start_gpu/8)]
        # 1 正方向leaf源路由
        comm_para_list_for_this_task.append(("R", "vlan_%s_acl"%start_vlan_id, "%s"%start_vlan_id, Port_ip_map.find_gpu_ip(start_gpu), Port_ip_map.find_spine_ip(int(leaf_outport)), "vlan %s"%start_vlan_id, "%s"%CURRENT_COMMAND_ID))
        CURRENT_COMMAND_ID += 1
    if dis_gpu>=int(GPU_NUM/2):
        # global CURRENT_COMMAND_ID
        comm_para_list_for_this_task.append(("H", Port_ip_map.find_gpu_ip(dis_gpu), Port_ip_map.find_spine_ip(int(leaf_inport)), Port_ip_map.find_hw_leaf_port(dis_gpu%32), CURRENT_COMMAND_ID))
        CURRENT_COMMAND_ID += 1
    else:
        # global CURRENT_COMMAND_ID
        dis_vlan_id = Port_ip_map.rg_vlan_list[int(dis_gpu/8)]
        # 3 反方向leaf源路由
        comm_para_list_for_this_task.append(("R", "vlan_%s_acl"%dis_vlan_id, "%s"%dis_vlan_id, Port_ip_map.find_gpu_ip(dis_gpu), Port_ip_map.find_spine_ip(int(leaf_inport)), "vlan %s"%dis_vlan_id, "%s"%CURRENT_COMMAND_ID))
        CURRENT_COMMAND_ID += 1
    #2 正方向spine目的路由
    if dis_gpu>=int(GPU_NUM/2):
        comm_para_list_for_this_task.append(("S", Port_ip_map.find_gpu_ip(dis_gpu), Port_ip_map.find_hw_leaf_ip((leaf_inport)%32), Port_ip_map.find_spine_port(leaf_outport), CURRENT_COMMAND_ID))
    else:
        comm_para_list_for_this_task.append(("S", Port_ip_map.find_gpu_ip(dis_gpu), Port_ip_map.find_rg_leaf_ip((leaf_inport)%32), Port_ip_map.find_spine_port(leaf_outport), CURRENT_COMMAND_ID))
    CURRENT_COMMAND_ID += 1
    #3 反方向spine目的路由
    if start_gpu>=int(GPU_NUM/2):
        comm_para_list_for_this_task.append(("S", Port_ip_map.find_gpu_ip(start_gpu), Port_ip_map.find_hw_leaf_ip((leaf_outport)%32), Port_ip_map.find_spine_port(leaf_inport), CURRENT_COMMAND_ID))
    else:
        comm_para_list_for_this_task.append(("S", Port_ip_map.find_gpu_ip(start_gpu), Port_ip_map.find_rg_leaf_ip((leaf_outport)%32), Port_ip_map.find_spine_port(leaf_inport), CURRENT_COMMAND_ID))
    CURRENT_COMMAND_ID += 1

    return comm_para_list_for_this_task

    
    


def control_eps(command_list_for_this_task, taskid):
    for comm_para_list_for_this_task in command_list_for_this_task:
        if comm_para_list_for_this_task[0] == "H":
            cmd = f'python3 switch_control/acl_hw.py --task_id {taskid} --inport {comm_para_list_for_this_task[3]} --source {comm_para_list_for_this_task[1]} --destination None --outport {comm_para_list_for_this_task[2]} --aclId {CURRENT_COMMAND_ID}'
        elif comm_para_list_for_this_task[0] == "S":
            cmd = f'python3 switch_control/acl_hw.py --task_id {taskid} --inport {comm_para_list_for_this_task[3]} --source None --destination {comm_para_list_for_this_task[1]} --outport {comm_para_list_for_this_task[2]} --aclId {CURRENT_COMMAND_ID}'
        else:
            cmd = f'python3 switch_control/acl_control_rg.py  --map_name {comm_para_list_for_this_task[1]} --map_id {comm_para_list_for_this_task[2]} --src_ip {comm_para_list_for_this_task[3]} --rdc_ip {comm_para_list_for_this_task[4]} --int {comm_para_list_for_this_task[5]} --acl_num {comm_para_list_for_this_task[6]}'
        print(cmd)
        #os.system(cmd)  

def read_task_from_file():
    flow_info = []
    txt = open('flow_info.txt', "r", encoding="utf-8-sig")
    for line in txt.readlines():
        line = line.strip()  
        temp_info_list = line.split(",")
        for i in range(len(temp_info_list)):
            temp_info_list[i] = int(temp_info_list[i])
        flow_info.append((temp_info_list[0],temp_info_list[1],temp_info_list[2],temp_info_list[3],temp_info_list[4],temp_info_list[5]))
    return flow_info


def main():
    task_id = 0
    flow_info_list = read_task_from_file()
    for flow_info in flow_info_list:
        comm_para_list_for_this_task = get_acl_para(flow_info)
        control_eps(comm_para_list_for_this_task, task_id)
        task_id += 1

if __name__ == "__main__":
    main()    
